# 定义类
class Foo(object):
    def __init__(self, name):
        self.name = name

    def __new__(cls, *args, **kwargs):
        return object.__new__(cls)


# 根据类创建对象
# 1 执⾏类的new⽅法，创建空对象 【构造⽅法】 {}
# 2 执⾏类的init⽅法，初始化对象 【初始化⽅法】{name:"luffy"}
obj = Foo("luffy")


# 传统⽅式创建类
class Foo2(object):
    v1 = 123

    @staticmethod
    def func():
        return 666


# ⾮传统⽅式创建类
Foo23 = type("Foo2", (object,), {"v1": 1232, "func": lambda self: 6662})
# ⾮传统⽅式创建对象
obj2 = Foo23()
# ⾮传统⽅式调⽤v1的变量
print(obj2.v1)

# 传统⽅式创建类(直观)
"""
class Foo(object):
v1 = 123

 def func(self):
 return 666
print(Foo)
"""
# ⾮传统⽅式（⼀⾏）
# 1 创建类型
# - 类名
# - 继承类
# - 成员
Fa = type("Foo", (object,), {"v1": 123, "func": lambda self: 666})
# 2 根据类创建对象
obj3 = Fa()
# 3 调⽤对象中的v1变量
print(obj3.v1)
# 4 执⾏对象中的func⽅法
result = obj3.func()


# type 创建Foo类
class Foo4(object):
    pass


class MyType(type):
    pass


class Foo5(object, metaclass=MyType):
    pass


# Foo类由MyType创建
class MyType2(type):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def __new__(cls, *args, **kwargs):
        new_cls = super().__new__(cls, *args, **kwargs)
        return new_cls

    def __call__(self, *args, **kwargs):
        # 调⽤⾃⼰的那个类 __new__ ⽅法去创建对象
        empty_object = self.__new__(self)
        # 调⽤你⾃⼰的__init__ ⽅法取初始化
        self.__init__(empty_object, *args, **kwargs)
        return empty_object


class Foo6(object, metaclass=MyType):
    def __init__(self, name):
        self.name = name


# 假设Foo是⼀个对象 由MyType创建
# Foo其实是MyType的⼀个对象
# Foo() -> MyType对象()
v1 = Foo6("alex")
print(v1)
print(v1.name)


class MyType3(type):
    def __init__(self, name, bases, attrs):
        super().__init__(name, bases, attrs)

        self.instance = None

    def __call__(self, *args, **kwargs):

        # 1判断是否有对象， 有不穿件
        if not self.instance:
            self.__init__(self.instance, *args, **kwargs)
        return self.instance


class Singleton(object, metaclass=MyType3):
    pass


class Foo7(Singleton, metaclass=MyType3):
    pass


class Foo8(Singleton):
    pass


v1 = Foo7()
v2 = Foo7()
print(v1)
print(v2)
